在上一章的實作中,我們完成了 Web API Container Image 的製作和上傳,接下來便要在 K8s 部署這個容器。在那之前讓我們先了解等會而使用到的資源。
在 Kubernetes 中,Pod 是最小的可部署計算單元,可以被看作是容器的再包裝,提供了更高級的抽象和管理功能。它是由一個以上的容器組成,這些容器共享存儲、網路和運行規範。這種包裝使得 Kubernetes 可以高效地調度和管理容器化應用,實現資源共享、簡化管理和提高可靠性。
以下是等下會使用的 Pod 組態檔案範例,使用 YAML 格式:
apiVersion: v1
kind: Pod
metadata:
labels:
app: foo
name: foo
spec:
containers:
- name: foo
image: lofairy/foo
apiVersion: v1
:指定使用的 Kubernetes API 版本為 v1。kind: Pod
:指定這個資源的類型是 Pod。metadata
:Pod 的元數據設定。
labels
:用來給 Pod 打標籤。在這裡,標籤 app: foo
可以用於組織和選擇 Pod。name: foo
:Pod 的名稱是 foo
。spec
:Pod 的規格設定。
containers
:這個 Pod 包含的容器設定。
name: foo
:容器的名稱是 foo
。image: lofairy/foo
:容器將使用 lofairy/foo
這個 Docker 鏡像來啟動。在 Kubernetes 中,Service 是一種抽象概念,定義了 Pod 如何被訪問,並確保即使 Pod 改變,服務的訪問方式也保持不變。
這裡我們會使用 Service 的其中一個類型 NodePort
,這個類型會將 Service 暴露在每個節點的某個靜態端口上,使得可以通過 <NodeIP>:<NodePort>
訪問該服務。
以下是等下會使用的 Service 組態檔案範例,使用 YAML 格式:
apiVersion: v1
kind: Service
metadata:
name: example-nodeport-service
spec:
type: NodePort
selector:
app: example-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 30007
apiVersion: v1
:指定使用的 Kubernetes API 版本為 v1。kind: Service
:指定這個資源的類型是 Service。metadata
:Service 的元數據設定。
name: example-nodeport-service
:Service 的名稱是 example-nodeport-service
。spec
:Service 的規格設定。
type: NodePort
:Service 的類型為 NodePort,使服務可通過集群中的每個節點的 IP 和指定的端口進行訪問。selector
:選擇器,用來選擇具有指定標籤的 Pod。
app: example-app
:選擇具有 app: example-app
標籤的 Pod。ports
:Service 的端口設定。
protocol: TCP
:使用的協議是 TCP。port: 80
:Service 暴露的端口號為 80。targetPort: 8080
:Service 轉發流量到 Pod 的端口號為 8080。nodePort: 30007
:每個節點上的靜態端口號為 30007,用於從外部訪問這個 Service。在 Kubernetes 中,標籤(Labels)和選擇器(Selectors)是兩個非常重要的概念,用於組織、篩選和管理集群中的資源,如 Pod、Service 等。它們為管理和調度容器化應用提供了靈活和強大的工具。
想像你有一大堆的資料,這些資料都是 Kubernetes 中的 Pod 或 Service。標籤就像是一張貼在這些資源上的「便利貼」,讓你能快速找到你想要的資料。每個標籤都是一對鍵和值,比如 app=myapp
,你可以隨意添加任何你想要的標籤來幫助你分類和管理這些資源。
舉個例子:
你有幾個 Pod,每個 Pod 上你都貼了一個標籤 app=myapp
,這樣一來你就可以很容易地透過選擇器或篩選器找到屬於 myapp
的所有 Pod。
選擇器就像是你用來尋找帶有特定標籤的 Pod 的「過濾器」。當你想做些事,比如將流量發送到一組特定的 Pod 時,你可以用選擇器來挑出那些符合條件的 Pod。
舉個例子:
假設你有個 Service,要將流量轉發到所有標籤為 app=myapp
的 Pod。你可以這樣寫:
selector:
app: myapp
這樣這個 Service 只會把流量發送到那些帶有 app=myapp
標籤的 Pod。
有時候,你可能想找出符合多個標籤條件的 Pod,這時候就要用到集合選擇器。比如,你想找出所有 environment
是 production
或 staging
的 Pod,你可以這樣做:
selector:
matchExpressions:
- key: environment
operator: In
values:
- production
- staging
這就好比在搜尋資料時說:「給我所有 environment
是 production
或 staging
的 Pod。」
今天我們的目標是使用 Pod 部署上一章建立的容器,並建立 Service 來暴露 Pod。示意圖如下:
組態檔案: pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
app: foo
name: foo
spec:
containers:
- name: foo
image: lofairy/foo
ports:
- containerPort: 8080 ## 標示 container 端口,沒標示不影響使用
kubectl apply -f pod.yaml
在沒有建立 Service 的情況下,要測試 Pod 內的 Web API,我們有兩種做法:
流量轉發
kubectl port-forward pods/foo 8080:8080
curl http://localhost:8080
---
foo
進入 Pod 內測試
wget
訪問容器本機端口kubectl exec foo -- sh -c "wget -q -O - 0.0.0.0:8080"
---
foo
得到回應,我們的容器已經正常在 Pod 內運作。
組態應用: service.yaml
apiVersion: v1
kind: Service
metadata:
name: foo
spec:
type: NodePort
selector:
app: foo
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 30000
kubectl apply -f service.yaml
由於我們在使用
KinD
建立叢集時,設定將本機的30000
端口流量轉發到 Kubernetes 叢集中的 NodePort30000
端口,僅需直接訪問localhost:30000
就可以訪問到上面的 Service。
curl 0.0.0.0:30000
---
foo
Service 作為中間層,讓我們可以訪問到實際運行程式的 Pod
到目前為止,我們已經成功訪問了部署在 Kubernetes 上的應用程式。然而,隨著高可用性和快速部署需求的增長,目前的部署方案顯然已不再足夠。
今天建立的 K8s 資源暫時不需要清理,因為我們將在明天的章節中繼續使用它們。